package com.ehotting.edsta.circuitDesign.gen.element;

import com.ehotting.edsta.circuitDesign.enums.SceneTypeEnum;
import com.ehotting.edsta.circuitDesign.enums.StateTypeEnum;
import com.ehotting.edsta.circuitDesign.domain.EsCircuitCodeDataTemplate;
import com.ehotting.edsta.circuitDesign.domain.EsRuleScript;
import com.ehotting.edsta.circuitDesign.domain.EsSceneParam;
import com.ehotting.edsta.circuitDesign.gen.ScriptConstants;
import com.ehotting.edsta.circuitDesign.gen.element.helper.ElementScriptHelper;
import com.ehotting.edsta.circuitDesign.gen.element.script.*;
import com.ehotting.edsta.circuitDesign.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

@Service
public class ElementScriptFactory {


    private static Logger logger = LoggerFactory.getLogger(ElementScriptFactory.class);

    @Autowired
    private IEsRuleScriptService esRuleScriptService;
    @Autowired
    private AssignmentElementScript assignmentElementScript;
    @Autowired
    private ConditionElementScript conditionElementScript;
    @Autowired
    private CustomElementScript customElementScript;
    @Autowired
    private FormulaElementScript formulaElementScript;
    @Autowired
    private RangeElementScript rangeElementScript;
    @Autowired
    protected ElementScriptHelper elementScriptHelper;


    private List<ElementScriptAble> codeList = new ArrayList();

    @PostConstruct
    public void init(){
        codeList.add(assignmentElementScript);
        codeList.add(rangeElementScript);
        codeList.add(conditionElementScript);
        codeList.add(customElementScript);
        codeList.add(formulaElementScript);
    }

    public String genMethod(Long sceneId, List<EsCircuitCodeDataTemplate> inputParamList, List<EsSceneParam> outputParamList) {

        StringBuffer buf = new StringBuffer();
        List<EsRuleScript> scriptList = esRuleScriptService.findBySceneIdAndTypeAndState(
                sceneId,
                SceneTypeEnum.ELEMENT_SELECT,
                StateTypeEnum.YES);
        for(EsRuleScript esRule: scriptList){
            genScript( esRule, buf,  inputParamList,  outputParamList);
        }
        return buf.toString();
    }


    public String genMethodByRuleScriptId(Long ruleScriptId, List<EsCircuitCodeDataTemplate> inputParamList, List<EsSceneParam> outputParamList) {
        StringBuffer buf = new StringBuffer();
        EsRuleScript esRuleScript = esRuleScriptService.selectEsRuleScriptById(ruleScriptId);
        genScript( esRuleScript, buf,  inputParamList,  outputParamList);
        return buf.toString();
    }


    private void genScript(EsRuleScript script, StringBuffer buf, List<EsCircuitCodeDataTemplate> inputParamList, List<EsSceneParam> outputParamList){
        for (ElementScriptAble code : codeList) {
            boolean isTrue = code.isTrue(script.getType());
            logger.info("code.getClass():{},isTrue:{},esRule.getType():{}", code.getClass(), isTrue, script.getType());
            if (isTrue) {
                buf.append(code.invoke(script,
                        inputParamList,
                        outputParamList,
                        getFunctionName(script)));
                buf.append(ScriptConstants.LINE);
            }
        }
    }


    public String genCallBySceneId(Long sceneId, List<EsCircuitCodeDataTemplate> inputParamList) {
        StringBuffer buf = new StringBuffer();
        List<EsRuleScript> scriptList = esRuleScriptService.findBySceneIdAndTypeAndState(sceneId, SceneTypeEnum.ELEMENT_SELECT, StateTypeEnum.YES);
        for(EsRuleScript esRule: scriptList){
            genCall( esRule, buf,  inputParamList);
        }
        return buf.toString();
    }


    public String genCallByRuleScriptId(Long ruleScriptId, List<EsCircuitCodeDataTemplate> inputParamList) {
        StringBuffer buf = new StringBuffer();
        EsRuleScript esRuleScript = esRuleScriptService.selectEsRuleScriptById(ruleScriptId);
        genCall( esRuleScript, buf,  inputParamList);
        return buf.toString();
    }

    private void genCall(EsRuleScript esRuleScript, StringBuffer buf, List<EsCircuitCodeDataTemplate> inputParamList){
        buf.append(ScriptConstants.TAB);
        buf.append(elementScriptHelper.genMethodNameAndArgument(getFunctionName(esRuleScript),inputParamList));
        buf.append( ";");
        buf.append(ScriptConstants.LINE);
    }

    private String getFunctionName(EsRuleScript script){
        return "element_"+script.getType().toString().toLowerCase() + "_"+script.getId();
    }

}
